using Caliburn.Micro;
using SS.Common.Logging;
using SS.WPF.Framework.Display.Dialog;
using SS.WPF.Framework.Display.MsgBox;
using SS.WPF.Framework.Localization;

namespace SS.WPF.Framework.ExceptionHandling
{
    using System;

    public class ExceptionProcessor : IExceptionContext, IExceptionProcessor, IExceptionHandler, IDialogManagerContainer
    {
        private static readonly ILogger Logger = LoggerManager.GetLogger(typeof(ExceptionProcessor).Name);

        private Exception CurrentException { get; set; }

        public IDialogManager DialogManager { get; set; }

        /// <summary>
        /// Return current happen exception. ExceptionProcessor will use this method 
        /// to determine is current ExceptionHandler support happen Exception or not
        /// </summary>
        /// <typeparam name="T">
        /// the typr of exception which want to get
        ///  </typeparam>
        /// <returns>
        /// exception with correct type 
        /// </returns>
        public T GetException<T>() where T : Exception
        {
            var targetException = CurrentException as T;
            if (targetException == null)
            {
                throw new UnSupportHandlerException("This handler not support this exception");
            }

            return targetException;
        }

        /// <summary>
        /// helpe to display error at current window
        /// </summary>
        /// <param name="ex">
        /// The exception
        /// </param>
        /// <param name="errparams">
        /// The errparams.
        /// </param>
        public void ShowErrorAtCurrentWindow(CustomException ex, object[] errparams)
        {
            ShowErrMsgBox(this, ex);
        }

        #region Implementation of IExceptionProcessor

        /// <summary>
        /// set IDialogManager
        /// </summary>
        /// <param name="dialogManager">
        /// The dialog manager.
        /// </param>
        public void SetDialogManager(IDialogManager dialogManager)
        {
            DialogManager = dialogManager;
        }

        /// <summary>
        /// Handle exception at client side
        /// </summary>
        /// <param name="ex">
        /// The ex to be handled
        /// </param>
        public void HandleException(Exception ex)
        {
            CurrentException = ex;
            HandleException(this);
        }

        #endregion

        #region Implementation of IExceptionHandler

        /// <summary>
        /// Handle exception
        /// </summary>
        /// <param name="context">
        /// The current context 
        /// </param>
        /// <exception cref="UnSupportHandlerException"></exception>
        public void HandleException(IExceptionContext context)
        {
            var exception = context.GetException<Exception>();
            try
            {
                var efpException = context.GetException<CustomException>();
                exception = efpException;
                context.ShowErrorAtCurrentWindow(efpException, efpException.ErrParams);
            }
            catch (UnSupportHandlerException)
            {
                ShowErrMsgBox(context, exception);
            }
            finally
            {
                Logger.Error("Exception happen.", exception);
            }
        }

        private void ShowErrMsgBox(IExceptionContext context, Exception exception)
        {
            var msgInfo = new MsgBoxInfo()
                {
                    Image = MsgBoxImage.Error,
                    Buttons = MsgBoxButtons.OK,
                    Heading = "Error",
                    Text = exception.Message,
                    Title = IoC.Get<TranslationManager>().Translate("EFPConfigurationTool") as string
                };

            context.DialogManager.ShowMessageBox(msgInfo);
        }

        #endregion

        #region Implementation of IExceptionContext

        /// <summary>
        /// Gets or sets DialogManager.
        /// </summary>
        IDialogManager IExceptionContext.DialogManager
        {
            get
            {
                return DialogManager;
            }
            set
            {
                DialogManager = value;
            }
        }

        #endregion
    }
}